#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>

void error(const char *msg)
{
    perror(msg);
    exit(1);
}

int main(int argc, char *argv[])
{
	int sock_descriptor, newsocket_descriptor, port_number;
	socklen_t clientlen;
	char buffer[256];
	struct sockaddr_in server_addr, client_addr;
	int n;
	
	if (argc < 2) {
		fprintf(stderr,"ERROR, tenes que especificar el puerto\n");
		exit(1);
	}
	
	sock_descriptor = socket(AF_INET, SOCK_STREAM, 0);
	if (sock_descriptor < 0){
		error("no se pudo abrir el socket");
	}
	
	// inicializo a cero todo el struct
	bzero((char *) &server_addr, sizeof(server_addr));
	
	// como parametro se le pasa el numero de puerto por el cual
	// va a estar escuchando el servidor
	port_number = atoi(argv[1]);
	
	server_addr.sin_family = AF_INET;
	server_addr.sin_addr.s_addr = INADDR_ANY;
	
	// esta funcion hace una cosa rara con el numero del
	// puerto que nunca entendi
	server_addr.sin_port = htons(port_number);
	
	// le digo al SO que me asocie el socket que abri con el puerto
	int bind_response = bind(sock_descriptor, (struct sockaddr *) &server_addr, sizeof(server_addr));
	if ( bind_response < 0){
		error("no se pudo asociar el socket con el puerto");
	}
	
	// me pongo a escuchar en el puerto a travez del socket
	listen(sock_descriptor,5);
	clientlen = sizeof(client_addr);
	// se bloquea la ejecucion hasta que se conecte un cliente 
	// y se acepte la conexion
	newsocket_descriptor = accept(sock_descriptor, (struct sockaddr *) &client_addr, &clientlen);
	
	if (newsocket_descriptor < 0){
		error("error al aceptar la conexion");
	}
	
	// inicializo en cero el buffer
	bzero(buffer, 256);
	// leo en el nuevo socket
	n = read(newsocket_descriptor, buffer, 255);
	
	if (n < 0){
		error("error al leer el socket");
	}
	
	// escribo en el socket
	n = write(newsocket_descriptor, "Este msg fue al Server y volvio: ", 33);
	n = write(newsocket_descriptor, buffer, 256);
	
	
	if (n < 0){
		error("error al escribir en el socket");
	}
	
	// cierro los dos socket que abri
	close(newsocket_descriptor);
	close(sock_descriptor);
	
	return 0; 
}
